'use strict'

/**
 * torrent - info
 */
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const md5File = require('md5-file');

const logger = require('./logger')('TorrentShareInfo');

const PIECE_SIZE = 262144;   // 每个piece的长度  256k


// 计算 info-hash
function calculateInfoHash(info) {
  const orderedInfo = {};
  Object.keys(info).sort().forEach(key => {
    orderedInfo[key] = info[key];
  });
  // 计算info 的sha1值
  const sha1 = crypto.createHash('sha1');
  sha1.update(JSON.stringify(orderedInfo));
  return sha1.digest('hex');
}


class TorrentShareInfo {
  constructor() {}

  /**
   * 生成文件分享信息
   * @param {*} filePath
   * @param {*} cb  (err, shareInfo)
   */
  static generate(filePath, cb) {
    logger.debug('generate torrent share info...');
    const ShareInfo = {
      info: {},
      infoHash: null,
    }

    fs.stat(filePath, (err, stats) => {
      if (err) {
        return cb(err);
      }
      ShareInfo.info = {
        name: path.basename(filePath),      // 文件名
        hash: null,                         // 文件hash
        size: stats.size,                   // 文件大小
        pieceSize: PIECE_SIZE,              // 每个piece的长度  256k
      }

      // 计算文件的MD5
      md5File(filePath, (err, hash) => {
        if (err) {
          return cb(err);
        }
        ShareInfo.info.hash = hash;
        ShareInfo.infoHash = calculateInfoHash(ShareInfo.info);
        logger.debug('finish.');
        cb(null, ShareInfo);
      });
    });
  }

  static check(shareInfo) {
    const keys = ['info', 'infoHash']
      , infoKeys = ['name', 'hash', 'size', 'pieceSize'];

    for (let key of keys) {
      if (!(key in shareInfo)) {
        logger.error(`${key} is missing in torrentShareInfo!`);
        return false;
      }
    }

    for (let key of infoKeys) {
      if (!(key in shareInfo.info)) {
        logger.error(`${key} is missing in torrentShareInfo.info!`);
        return false;
      }
    }

    const infoHash = calculateInfoHash(shareInfo.info);
    if (infoHash !== shareInfo.infoHash) {
      logger.error(`infoHash is not correct!`);
      return false;
    }
    return true;
  }
}

module.exports.TorrentShareInfo = TorrentShareInfo;
